#tag Class
Protected Class GameBoard
	#tag Method, Flags = &h0
		Function AddTileAtPosition(newTile as Tile, position as Coordinates) As boolean
		  dim i as integer
		  dim myPos as Coordinates
		  dim otherPos as Coordinates
		  dim possibleCoords() as Coordinates
		  dim valid as boolean = false
		  
		  if GetPositionIsFree(position) = true then
		    possibleCoords = GetPossibleCoordinatesForTile(newTile)
		    for i = 0 to UBound(possibleCoords)
		      if position.x = possibleCoords(i).x and _
		        position.y = possibleCoords(i).y then
		        valid = true
		        exit for
		      end if
		    next i
		    
		    if valid = false and i > 0 then exit function
		    
		    newTile.SetPosition position
		    newTile.PlaceTile self
		    
		    myPos = newTile.GetPosition
		    
		    for i = 0 to UBound(tiles)
		      otherPos = tiles(i).GetPosition
		      if otherPos.x = myPos.x and otherPos.y = myPos.y + 1  then
		        newTile.SetNorthNeighbor tiles(i)
		        tiles(i).SetSouthNeighbor newTile
		      elseif otherPos.x = myPos.x + 1 and otherPos.y = myPos.y then
		        newTile.SetEastNeighbor tiles(i)
		        tiles(i).SetWestNeighbor newTile
		      elseif otherpos.x = myPos.x and otherPos.y = myPos.y -1 then
		        newTile.SetSouthNeighbor tiles(i)
		        tiles(i).SetNorthNeighbor newTile
		      elseif otherpos.x = myPos.x - 1 and otherPos.y = myPos.y then
		        newTile.SetWestNeighbor tiles(i)
		        tiles(i).SetEastNeighbor newTile
		      end if
		    next
		    
		    tiles.Append newTile
		    return true
		  else
		    return false
		  end if
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetPossibleCoordinatesForTile(currentTile as Tile) As Coordinates()
		  dim i, j as integer
		  dim valid as boolean
		  dim posArray() as Coordinates
		  dim negArray() as Coordinates
		  dim finalArray() as Coordinates
		  
		  
		  'first of all we iterate over all tiles on the
		  'gameboard and check if it is possible to place
		  'the new tile on either side of the current tile
		  'if yes then we add the position to a positive set,
		  'if not we add it to a negative set.
		  'at the end we check each tile in the positive set
		  'and add it only then to the final set, if the position
		  'is not included in the negative set. This prevents
		  'situations in which a position might be valid for a
		  'tile while it isn't for another tile
		  
		  for i = 0 to UBound(tiles)
		    dim position as Coordinates
		    dim sides as Sides
		    position = tiles(i).GetPosition
		    sides = tiles(i).GetPossibleSides(currentTile)
		    
		    dim northSide as Coordinates
		    northSide.x = position.x
		    northSide.y = position.y + 1
		    
		    if  sides.north = true then
		      posArray.Append northside
		    else
		      negArray.Append northside
		    end if
		    
		    dim eastSide as Coordinates
		    eastSide.x = position.x +1
		    eastSide.y = position.y
		    
		    if sides.east = true then
		      posArray.Append eastSide
		    else
		      negArray.Append eastSide
		    end if
		    
		    dim southSide as Coordinates
		    southSide.x = position.x
		    southSide.y = position.y -1
		    
		    if sides.south = true then
		      posArray.Append southSide
		    else
		      negArray.Append southSide
		    end if
		    
		    dim westSide as Coordinates
		    westSide.x = position.x -1
		    westSide.y = position.y
		    
		    if sides.west = true then
		      posArray.Append westSide
		    else
		      negArray.Append westSide
		    end if
		  next i
		  
		  for i = 0 to ubound(posArray)
		    valid = true
		    for j = 0 to ubound(negArray)
		      if posArray(i).x = negArray(j).x and posArray(i).y = negArray(j).y then
		        valid = false
		        'exit for i
		      end if
		    next j
		    if valid = true then
		      finalArray.Append posArray(i)
		    end if
		  next i
		  
		  return finalArray
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Sub Constructor()
		  dim startTile as new Tile
		  dim northSide as new Town(startTile)
		  dim eastSide as new Street(startTile)
		  dim southSide as new Grassland(startTile)
		  dim westSide as new Street(startTile)
		  dim startPos as Coordinates
		  dim sCon as Connections
		  dim tcon as Connections
		  
		  
		  startTile.id = 1
		  startTile.SetUid "Starttile"
		  
		  sCon.north = false
		  sCon.east = true
		  scon.south = false
		  scon.west = true
		  
		  tcon.north = false
		  tcon.east = false
		  tcon.south = false
		  tcon.west = false
		  
		  startTile.SetNorthSection (northSide)
		  startTile.SetEastSection(eastSide)
		  startTile.SetSouthSection(southSide)
		  startTile.SetWestSection(westSide)
		  
		  startTile.grid.SetSlot("n", 3)
		  startTile.grid.SetSlot("ne", 1)
		  startTile.grid.SetSlot("c", 2)
		  startTile.grid.SetSlot("s", 1)
		  
		  starttile.SetIsSingleTown true
		  starttile.SetStreetConnections scon
		  starttile.SetTownConnections tcon
		  
		  startTile.northPicture = Start_100x100
		  
		  startPos.x = 0
		  startPos.y = 0
		  
		  call AddTileAtPosition startTile, startPos
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetPositionIsFree(position as Coordinates) As boolean
		  dim i as integer
		  dim tilePos as Coordinates
		  
		  
		  for i = 0 to UBound(tiles)
		    tilePos = tiles(i).GetPosition
		    if tilePos.x = position.x and tilePos.y = position.y then return false
		  next
		  
		  return true
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetTiles() As Tile()
		  return tiles
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetTileByPosition(pos as coordinates) As Tile
		  dim cur as Coordinates
		  
		  for each t as Tile in tiles
		    cur = t.GetPosition
		    if cur.x = pos.x and cur.y = pos.y then
		      return t
		    end if
		  next
		  
		  return nil
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetPossibleOccupieableTownCoordinates(currentTile as Tile) As Coordinates
		  'dim possibleCoordinates() as coordinates
		  'dim i as integer
		  '
		  'possibleCoordinates = GetPossibleCoordinatesForTile(currentTile)
		  '
		  '//todo
		  '
		  'for i = 0 to ubound(possibleCoordinates)
		  '//northNeighbor
		  'if
		  '
		  '
		  '
		  '
		  'next i
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetPositionIsOccupieableTown(pos as coordinates, p as game . player) As boolean
		  dim occupieable as boolean = true
		  dim helperCoordinates as Coordinates
		  dim theTile as Tile
		  
		  //northNeighbor
		  helperCoordinates.x = pos.x
		  helperCoordinates.y = pos.y +1
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil then
		    occupieable = theTile.GetIsOccupieableTown(p)
		  end if
		  //eastNeighbor
		  helperCoordinates.x = pos.x + 1
		  helperCoordinates.y = pos.y
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil and occupieable = true then
		    occupieable = theTile.GetIsOccupieableTown(p)
		  end if
		  //southneighbor
		  helperCoordinates.x = pos.x
		  helperCoordinates.y = pos.y - 1
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil and occupieable = true then
		    occupieable = theTile.GetIsOccupieableTown(p)
		  end if
		  //westneighbor
		  helperCoordinates.x = pos.x -1
		  helperCoordinates.y = pos.y
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil and occupieable = true then
		    occupieable = theTile.GetIsOccupieableTown(p)
		  end if
		  
		  return occupieable
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetPositionIsOccupieableStreet(pos as coordinates, p as game . player) As boolean
		  dim occupieable as boolean = true
		  dim helperCoordinates as Coordinates
		  dim theTile as Tile
		  
		  //northNeighbor
		  helperCoordinates.x = pos.x
		  helperCoordinates.y = pos.y +1
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil then
		    occupieable = theTile.GetIsOccupieableStreet(p)
		  end if
		  //eastNeighbor
		  helperCoordinates.x = pos.x + 1
		  helperCoordinates.y = pos.y
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil and occupieable = true then
		    occupieable = theTile.GetIsOccupieableStreet(p)
		  end if
		  //southneighbor
		  helperCoordinates.x = pos.x
		  helperCoordinates.y = pos.y - 1
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil and occupieable = true then
		    occupieable = theTile.GetIsOccupieableStreet(p)
		  end if
		  //westneighbor
		  helperCoordinates.x = pos.x -1
		  helperCoordinates.y = pos.y
		  theTile = GetTileByPosition(helperCoordinates)
		  if theTile <> nil and occupieable = true then
		    occupieable = theTile.GetIsOccupieableStreet(p)
		  end if
		  
		  return occupieable
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetNumberOfNeighbors(position as coordinates) As Integer
		  dim pos as Coordinates
		  dim number as integer = 0
		  
		  
		  //x..
		  //...
		  //...
		  pos.x = position.x -1
		  pos.y = position.y +1
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //.x.
		  //...
		  //...
		  pos.x = position.x
		  pos.y = position.y +1
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //..x
		  //...
		  //...
		  pos.x = position.x +1
		  pos.y = position.y +1
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //x..
		  //...
		  pos.x = position.x -1
		  pos.y = position.y
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //..x
		  //...
		  pos.x = position.x +1
		  pos.y = position.y
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //...
		  //x..
		  pos.x = position.x -1
		  pos.y = position.y -1
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //...
		  //.x.
		  pos.x = position.x
		  pos.y = position.y -1
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //...
		  //..x
		  pos.x = position.x +1
		  pos.y = position.y -1
		  
		  if GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  return number
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function GetTilesByOwner(owner as game.Player) As Tile()
		  dim owned() as Tile
		  
		  
		  
		  for each t as Tile in tiles
		    dim o as game.Player
		    o = t.GetOwner
		    if o <> nil then
		      if o = owner then
		        owned.append t
		      end if
		    end if
		  next
		  
		  return owned
		  
		End Function
	#tag EndMethod


	#tag Property, Flags = &h21
		Private tiles() As tile
	#tag EndProperty


	#tag ViewBehavior
		#tag ViewProperty
			Name="Name"
			Visible=true
			Group="ID"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Index"
			Visible=true
			Group="ID"
			InitialValue="-2147483648"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Super"
			Visible=true
			Group="ID"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Left"
			Visible=true
			Group="Position"
			InitialValue="0"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Top"
			Visible=true
			Group="Position"
			InitialValue="0"
			InheritedFrom="Object"
		#tag EndViewProperty
	#tag EndViewBehavior
End Class
#tag EndClass
